﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ControlExtension.cs" company="">
//   
// </copyright>
// <summary>
//   The control extension.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.Controls
{
    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    /// <summary>
    /// The control extension.
    /// </summary>
    public static class ControlExtension
    {
        #region Constants

        /// <summary>
        /// The c b_ setcuebanner.
        /// </summary>
        private const int CB_SETCUEBANNER = 0x1703;

        /// <summary>
        /// The e m_ getcuebanner.
        /// </summary>
        private const int EM_GETCUEBANNER = 0x1502;

        /// <summary>
        /// The e m_ setcuebanner.
        /// </summary>
        private const int EM_SETCUEBANNER = 0x1501;

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The set cue banner.
        /// </summary>
        /// <param name="control">
        /// The control.
        /// </param>
        /// <param name="text">
        /// The text.
        /// </param>
        /// <param name="showWhenFocus">
        /// The show when focus.
        /// </param>
        public static void SetCueBanner(this Control control, string text, bool showWhenFocus = false)
        {
            var b = showWhenFocus ? 1 : 0;

            if (control is ComboBox)
            {
                var info = GetComboBoxInfo(control);
                SendMessage(control.Handle, CB_SETCUEBANNER, b, text);
            }
            else
            {
                SendMessage(control.Handle, EM_SETCUEBANNER, b, text);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The get combo box info.
        /// </summary>
        /// <param name="hwnd">
        /// The hwnd.
        /// </param>
        /// <param name="pcbi">
        /// The pcbi.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        [DllImport("user32.dll")]
        private static extern bool GetComboBoxInfo(IntPtr hwnd, ref COMBOBOXINFO pcbi);

        /// <summary>
        /// The get combo box info.
        /// </summary>
        /// <param name="control">
        /// The control.
        /// </param>
        /// <returns>
        /// The <see cref="COMBOBOXINFO"/>.
        /// </returns>
        private static COMBOBOXINFO GetComboBoxInfo(Control control)
        {
            var info = new COMBOBOXINFO();
            info.cbSize = Marshal.SizeOf(info);
            GetComboBoxInfo(control.Handle, ref info);
            return info;
        }

        /// <summary>
        /// The send message.
        /// </summary>
        /// <param name="hWnd">
        /// The h wnd.
        /// </param>
        /// <param name="msg">
        /// The msg.
        /// </param>
        /// <param name="wParam">
        /// The w param.
        /// </param>
        /// <param name="lParam">
        /// The l param.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SendMessage(
            IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);

        #endregion

        /// <summary>
        /// The comboboxinfo.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct COMBOBOXINFO
        {
            /// <summary>
            /// The cb size.
            /// </summary>
            public int cbSize;

            /// <summary>
            /// The rc item.
            /// </summary>
            public readonly RECT rcItem;

            /// <summary>
            /// The rc button.
            /// </summary>
            public readonly RECT rcButton;

            /// <summary>
            /// The state button.
            /// </summary>
            public readonly IntPtr stateButton;

            /// <summary>
            /// The hwnd combo.
            /// </summary>
            public readonly IntPtr hwndCombo;

            /// <summary>
            /// The hwnd item.
            /// </summary>
            public readonly IntPtr hwndItem;

            /// <summary>
            /// The hwnd list.
            /// </summary>
            public readonly IntPtr hwndList;
        }

        /// <summary>
        /// The rect.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            /// <summary>
            /// The left.
            /// </summary>
            public readonly int left;

            /// <summary>
            /// The top.
            /// </summary>
            public readonly int top;

            /// <summary>
            /// The right.
            /// </summary>
            public readonly int right;

            /// <summary>
            /// The bottom.
            /// </summary>
            public readonly int bottom;
        }
    }
}